home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / mach / sun3.md / machCode.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  56KB  |  1,843 lines

  1. /* 
  2.  * machCode.c --
  3.  *
  4.  *     C code for the mach module.
  5.  *
  6.  * Copyright 1989 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/mach/sun3.md/machCode.c,v 9.19 91/10/10 12:08:22 shirriff Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include <sprite.h>
  21. #include <assert.h>
  22. #include <stddef.h>
  23. #include <stdio.h>
  24.  
  25. #include <machConst.h>
  26. #include <machMon.h>
  27. #include <machInt.h>
  28. #include <mach.h>
  29. #include <sys.h>
  30. #include <sync.h>
  31. #include <dbg.h>
  32. #include <proc.h>
  33. #include <procMigrate.h>
  34. #include <prof.h>
  35. #include <sched.h>
  36. #include <vm.h>
  37. #include <vmMach.h>
  38. #include <sig.h>
  39. #include <swapBuffer.h>
  40. #include <user/sigMach.h>
  41. #include <user/sun3.md/sys/machSignal.h>
  42. #include <procUnixStubs.h>
  43. #include <compatInt.h>
  44. #include <sigUnixStubs.h>
  45.  
  46. int    machLastSP, machPOP;
  47.  
  48. /*
  49.  *  Number of processors in the system.
  50.  */
  51. #ifndef NUM_PROCESSORS
  52. #define NUM_PROCESSORS 1
  53. #endif /* NUM_PROCESSORS */
  54.  
  55. int mach_NumProcessors = NUM_PROCESSORS;
  56.  
  57. /*
  58.  * TRUE if cpu was in kernel mode before the interrupt, FALSE if was in 
  59.  * user mode.
  60.  */
  61. Boolean    mach_KernelMode;
  62.  
  63. /*
  64.  *  Flag used by routines to determine if they are running at
  65.  *  interrupt level.
  66.  */
  67. Boolean mach_AtInterruptLevel = FALSE;
  68.  
  69. extern int debugProcStubs;
  70.  
  71. /*
  72.  * The machine type string is imported by the file system and
  73.  * used when expanding $MACHINE in file names.
  74.  */
  75.  
  76. #ifdef sun3
  77. char *mach_MachineType = "sun3";
  78. #endif
  79. #ifdef sun2
  80. char *mach_MachineType = "sun2";
  81. #endif
  82.  
  83. extern int debugProcStubs;
  84.  
  85. /*
  86.  * The byte ordering/alignment type used with Fmt_Convert and I/O control data
  87.  */
  88. Fmt_Format mach_Format = FMT_68K_FORMAT;
  89.  
  90. /*
  91.  *  Count of number of ``calls'' to enable interrupts minus number of calls
  92.  *  to disable interrupts.  Kept on a per-processor basis.
  93.  */
  94. int mach_NumDisableInterrupts[NUM_PROCESSORS];
  95. int *mach_NumDisableIntrsPtr = mach_NumDisableInterrupts;
  96.  
  97. /*
  98.  * The format that the kernel stack has to be in to start a process off.
  99.  */
  100. typedef struct {
  101.     int        magicNumber;        /* Magic number used to determine if
  102.                      * the stack has been corrupted. */
  103.     Address    userStackPtr;        /* The user's stack pointer. */
  104.     short    statusReg;        /* The status register. */
  105.     void    (*startFunc)();        /* Function to call when process
  106.                      * first starts executing. */
  107.     int        retPC;            /* Return PC that will be sitting on the
  108.                      * stack when startFunc is called. */
  109.     Address    startPC;        /* PC to start executing at.  Is passed
  110.                      * as an argument to startFunc. */
  111.     int        fill1;            /* Filler for the debugger. */
  112.     int        fill2;            /* Filler for the debugger. */
  113. } KernelStack;
  114.  
  115. /*
  116.  * The format of a signal stack that is pushed onto a user's stack when
  117.  * a signal is handled.
  118.  */
  119. typedef struct {
  120.     Address    retAddr;
  121.     Sig_Stack    sigStack;
  122.     Sig_Context    sigContext;
  123. } SignalStack;
  124.  
  125. typedef struct UnixSignalStack {
  126.     int sigNum;
  127.     int sigCode;
  128.     struct sigcontext *sigContextPtr;
  129.     int sigAddr;
  130.     struct sigcontext sigContext;
  131. } UnixSignalStack;
  132.  
  133. /*
  134.  * Machine dependent variables.
  135.  */
  136. Address    mach_KernStart;
  137. Address    mach_CodeStart;
  138. Address    mach_StackBottom;
  139. int    mach_KernStackSize;
  140. Address    mach_KernEnd;
  141. Address    mach_FirstUserAddr;
  142. Address    mach_LastUserAddr;
  143. Address    mach_MaxUserStackAddr;
  144. int    mach_LastUserStackPage;
  145.  
  146. extern    int        MachGetVBR();
  147. MachVectorTable        *machVectorTablePtr;
  148. int            ((*machInterruptRoutines[256])());
  149. ClientData        machInterruptArgs[256];
  150.  
  151.  
  152. /*
  153.  * The variables and tables below are used by the assembler routine
  154.  * in machTrap.s that dispatches kernel calls.  All of this information
  155.  * is shared with machTrap.s;  if you change any of this, be sure to
  156.  * change the assembler to match.
  157.  */
  158.  
  159. #define MAXCALLS 120
  160. #define MAXARGS  16
  161.  
  162. int machMaxSysCall;            /* Highest defined system call. */
  163. int machArgOffsets[MAXCALLS];        /* For each system call, tells how much
  164.                      * to add to the sp at the time of the
  165.                      * call to get to the highest argument
  166.                      * on the stack. */
  167. Address machArgDispatch[MAXCALLS];    /* For each system call, gives an
  168.                      * address to branch to, in the middle
  169.                      * of MachFetchArgs, to copy the right
  170.                      * # of args from user space to the
  171.                      * kernel's stack. */
  172. ReturnStatus (*(mach_NormalHandlers[MAXCALLS]))();
  173.                     /* For each system call, gives the
  174.                      * address of the routine to handle
  175.                      * the call for non-migrated processes.
  176.                      */
  177. ReturnStatus (*(mach_MigratedHandlers[MAXCALLS]))();
  178.                     /* For each system call, gives the
  179.                      * address of the routine to handle
  180.                      * the call for migrated processes. */
  181. int machKcallTableOffset;        /* Byte offset of the kcallTable field
  182.                      * in a Proc_ControlBlock. */
  183. int machStatePtrOffset;            /* Byte offset of the machStatePtr
  184.                      * field in a Proc_ControlBlock. */
  185. int machSpecialHandlingOffset;        /* Byte offset of the specialHandling
  186.                      * field in a Proc_ControlBlock. */
  187. /* 
  188.  * Pointer to the state structure for the current process.
  189.  */
  190. Mach_State    *machCurStatePtr = (Mach_State *)NIL;
  191.  
  192. MachMonBootParam    machMonBootParam;
  193.  
  194. static void SetupSigHandler _ARGS_((register Proc_ControlBlock *procPtr, register SignalStack *sigStackPtr, Address pc));
  195. static void ReturnFromSigHandler _ARGS_((register Proc_ControlBlock *procPtr));
  196.  
  197.  
  198. /*
  199.  * ----------------------------------------------------------------------------
  200.  *
  201.  * Mach_Init --
  202.  *
  203.  *    Initialize the exception vector table and some of the dispatching
  204.  *    tables.
  205.  *
  206.  * Results:
  207.  *    None.
  208.  *
  209.  * Side effects:
  210.  *    The exception vector table is initialized.
  211.  *
  212.  * ----------------------------------------------------------------------------
  213.  */
  214. void
  215. Mach_Init()
  216. {
  217.     int    *vecTablePtr;
  218.     int    *protoVecTablePtr;
  219.     int    i;
  220.     int    offset;
  221.  
  222.     /*
  223.      * Set exported machine dependent variables.
  224.      */
  225.     mach_KernStart = (Address)MACH_KERN_START;
  226.     mach_KernEnd = (Address)MACH_KERN_END;
  227.     mach_CodeStart = (Address)MACH_CODE_START;
  228.     mach_StackBottom = (Address)MACH_STACK_BOTTOM;
  229.     mach_KernStackSize = MACH_KERN_STACK_SIZE;
  230.     mach_FirstUserAddr = (Address)MACH_FIRST_USER_ADDR;
  231.     mach_LastUserAddr = (Address)MACH_LAST_USER_ADDR;
  232.     mach_MaxUserStackAddr = (Address)MACH_MAX_USER_STACK_ADDR;
  233.     mach_LastUserStackPage = (MACH_MAX_USER_STACK_ADDR - 1) / VMMACH_PAGE_SIZE;
  234.  
  235.     /*
  236.      * Copy the boot parameter structure. The original location will get
  237.      * unmapped during vm initialization so we need to get our own copy.
  238.      */
  239.     machMonBootParam = **(romVectorPtr->bootParam);
  240.     offset = (int) *(romVectorPtr->bootParam) - (int) &(machMonBootParam);
  241.     for (i = 0; i < 8; i++) {
  242.     if (machMonBootParam.argPtr[i] != (char *) 0 &&
  243.      machMonBootParam.argPtr[i] != (char *) NIL) {
  244.         machMonBootParam.argPtr[i] -= offset;
  245.     }
  246.     }
  247.     /*
  248.      * Clear out the line input buffer to the prom so we don't get extra
  249.      * characters at the end of shorter reboot strings.
  250.      */
  251.     bzero((Address) romVectorPtr->lineBuf, *romVectorPtr->lineSize);
  252.     /*
  253.      * Initialize the vector table.
  254.      */
  255.     vecTablePtr = (int *) MachGetVBR();
  256.     machVectorTablePtr = (MachVectorTable *) vecTablePtr;
  257.     protoVecTablePtr = (int *) &machProtoVectorTable;
  258.     for (i = 0; i < MACH_NUM_EXCEPTIONS; i++) {
  259.     if (*protoVecTablePtr != 0) {
  260.          *vecTablePtr = *protoVecTablePtr;
  261.     }
  262.  
  263.     vecTablePtr++;
  264.     protoVecTablePtr++;
  265.     }
  266.  
  267. #ifdef sun3
  268.     /*
  269.      * Initialize the autovector interrupt slots.
  270.      */
  271.     for (i = MACH_NUM_EXCEPTIONS ; i<256 ; i++) {
  272.     extern int MachBrkptTrap();
  273.  
  274.     *vecTablePtr = (int)MachBrkptTrap;
  275.     vecTablePtr++;
  276.     }
  277. #endif sun3
  278. #ifndef sun3
  279.     /*
  280.      * Put the vectors at the base of the kernel if are on a Sun-2 only.  On
  281.      * a Sun-3 they can stay where they are.  The vectors on the Sun-2 can
  282.      * be moved this easily because virtual address 0 which is where the
  283.      * vector table is at, points to the same physical page as virtual address 
  284.      * mach_KernStart.
  285.      */
  286.     MachSetVBR(mach_KernStart);
  287.     machVectorTablePtr = (MachVectorTable *) mach_KernStart;
  288. #endif
  289.  
  290.     /*
  291.      * Initialize some of the dispatching information.  The rest is
  292.      * initialized by Mach_InitSysCall below.
  293.      */
  294.     machMaxSysCall = -1;
  295.     machKcallTableOffset = (int) &((Proc_ControlBlock *) 0)->kcallTable;
  296.     machStatePtrOffset = (int) &((Proc_ControlBlock *) 0)->machStatePtr;
  297.     machSpecialHandlingOffset = (int) 
  298.                 &((Proc_ControlBlock *) 0)->specialHandling;
  299.  
  300.     /*
  301.      * We start off with interrupts disabled.
  302.      */
  303.     mach_NumDisableInterrupts[0] = 1;
  304. }
  305.  
  306.  
  307.  
  308. /*
  309.  *----------------------------------------------------------------------
  310.  *
  311.  * Mach_InitFirstProc --
  312.  *
  313.  *    Initialize the machine state struct for the very first process.
  314.  *
  315.  * Results:
  316.  *    None.
  317.  *
  318.  * Side effects:
  319.  *    Machine info allocated and stack start set up.
  320.  *
  321.  *----------------------------------------------------------------------
  322.  */
  323. void
  324. Mach_InitFirstProc(procPtr)
  325.     Proc_ControlBlock    *procPtr;
  326. {
  327.  
  328.     assert(offsetof(Proc_ControlBlock, unixErrno) == MACH_UNIX_ERRNO_OFFSET);
  329.     procPtr->machStatePtr = (Mach_State *)Vm_RawAlloc(sizeof(Mach_State));
  330.     bzero((Address) procPtr->machStatePtr, sizeof(*procPtr->machStatePtr));
  331.     procPtr->machStatePtr->kernStackStart = mach_StackBottom;
  332.     machCurStatePtr = procPtr->machStatePtr;
  333. }
  334.  
  335.  
  336. /*
  337.  *----------------------------------------------------------------------
  338.  *
  339.  * Mach_SetupNewState --
  340.  *
  341.  *    Initialize the machine state for this process.  This includes 
  342.  *    allocating and initializing a kernel stack.  Assumed that will
  343.  *    be called when starting a process after a fork or restarting a
  344.  *    process after a migration.
  345.  *
  346.  * Results:
  347.  *    PROC_NO_STACKS if couldn't allocate a kernel stack.  SUCCESS otherwise.
  348.  *
  349.  * Side effects:
  350.  *    Machine state in the destination process control block is overwritten.
  351.  *
  352.  *----------------------------------------------------------------------
  353.  */ 
  354. ReturnStatus
  355. Mach_SetupNewState(procPtr, fromStatePtr, startFunc, startPC, user)
  356.     Proc_ControlBlock    *procPtr;    /* Pointer to process control block
  357.                      * to initialize state for. */
  358.     Mach_State        *fromStatePtr;    /* State of parent on fork or from
  359.                      * other machine on migration. */
  360.     void        (*startFunc)();    /* Function to call when process first
  361.                      * starts executing. */
  362.     Address        startPC;    /* Address to pass as argument to 
  363.                      * startFunc.  If NIL then the address
  364.                      * is taken from *fromStatePtr's 
  365.                      * exception stack. */
  366.     Boolean        user;        /* TRUE if is a user process. */
  367. {
  368.     register    KernelStack    *stackPtr;
  369.     register    Mach_State    *statePtr;
  370.  
  371.     if (procPtr->machStatePtr == (Mach_State *)NIL) {
  372.     procPtr->machStatePtr = (Mach_State *)Vm_RawAlloc(sizeof(Mach_State));
  373.     }
  374.     bzero((Address) procPtr->machStatePtr, sizeof(*procPtr->machStatePtr));
  375.     statePtr = procPtr->machStatePtr;
  376.     /* 
  377.      * Allocate a kernel stack for this process.
  378.      */
  379.     statePtr->kernStackStart = Vm_GetKernelStack(0);
  380.     if (statePtr->kernStackStart == (Address)NIL) {
  381.     return(PROC_NO_STACKS);
  382.     }
  383.  
  384.     statePtr->switchRegs[SP] = (int)(statePtr->kernStackStart + 
  385.                          MACH_KERN_STACK_SIZE - 
  386.                      sizeof(KernelStack));
  387.  
  388.     /*
  389.      * Initialize the stack so that it looks like it is in the middle of
  390.      * Mach_ContextSwitch.
  391.      */
  392.     stackPtr = (KernelStack *)(statePtr->switchRegs[SP]);
  393.     stackPtr->magicNumber = MAGIC;
  394.     stackPtr->userStackPtr = mach_MaxUserStackAddr;
  395.     stackPtr->statusReg = MACH_SR_HIGHPRIO;
  396.     stackPtr->startFunc =  startFunc;
  397.     stackPtr->fill1 = 0;
  398.     stackPtr->fill2 = 0;
  399.     /* 
  400.      * Set up the state of the process.  User processes inherit from their
  401.      * parent or the migrated process.  If the PC is not specified, take it
  402.      * from the parent as well.
  403.      */
  404.     if (user) {
  405.     statePtr->userState.userStackPtr =
  406.         fromStatePtr->userState.userStackPtr;
  407.     bcopy((Address)fromStatePtr->userState.trapRegs,
  408.           (Address)statePtr->userState.trapRegs,
  409.           sizeof(statePtr->userState.trapRegs));
  410. #ifdef sun3
  411.     bcopy((Address)fromStatePtr->userState.trapFpRegs,
  412.           (Address)statePtr->userState.trapFpRegs,
  413.           sizeof(statePtr->userState.trapFpRegs));
  414.     bcopy((Address)fromStatePtr->userState.trapFpCtrlRegs,
  415.           (Address)statePtr->userState.trapFpCtrlRegs,
  416.           sizeof(statePtr->userState.trapFpCtrlRegs));
  417.     bcopy((Address) &fromStatePtr->userState.trapFpuState,
  418.           (Address) &statePtr->userState.trapFpuState,
  419.           sizeof(statePtr->userState.trapFpuState));
  420. #endif
  421.     }
  422.     if (startPC == (Address)NIL) {
  423.     stackPtr->startPC = (Address)fromStatePtr->userState.excStackPtr->pc;
  424.     } else {
  425.     stackPtr->startPC = startPC;
  426.     }
  427.     return(SUCCESS);
  428. }
  429.  
  430. /*
  431.  *----------------------------------------------------------------------
  432.  *
  433.  * Mach_SetReturnVal --
  434.  *
  435.  *    Set the return value for a process from a system call.  Intended to
  436.  *    be called by the routine that starts a user process after a fork.
  437.  *
  438.  * Results:
  439.  *    None.
  440.  *
  441.  * Side effects:
  442.  *    Register D0 is set in the user registers.
  443.  *
  444.  *----------------------------------------------------------------------
  445.  */ 
  446. void
  447. Mach_SetReturnVal(procPtr, retVal, retVal2)
  448.     Proc_ControlBlock    *procPtr;    /* Process to set return value for. */
  449.     int            retVal;        /* Value for process to return. */
  450.     int            retVal2;    /* Second return value. */
  451. {
  452.     procPtr->machStatePtr->userState.trapRegs[D0] = retVal;
  453.     procPtr->machStatePtr->userState.trapRegs[D1] = retVal2;
  454. }
  455.  
  456.  
  457. /*
  458.  *----------------------------------------------------------------------
  459.  *
  460.  * Mach_StartUserProc --
  461.  *
  462.  *    Start a user process executing for the first time.
  463.  *
  464.  * Results:
  465.  *    None.
  466.  *
  467.  * Side effects:
  468.  *    Stack pointer and the program counter set for the process and
  469.  *    the current process's image is replaced.
  470.  *
  471.  *----------------------------------------------------------------------
  472.  */
  473. void
  474. Mach_StartUserProc(procPtr, entryPoint)
  475.     Proc_ControlBlock    *procPtr;    /* Process control block for process
  476.                      * to start. */
  477.     Address        entryPoint;    /* Where process is to start
  478.                      * executing. */
  479. {
  480.     register    Mach_State    *statePtr;
  481.     register    Mach_ExcStack    *excStackPtr;
  482.  
  483.     statePtr = procPtr->machStatePtr;
  484.     excStackPtr = (Mach_ExcStack *)
  485.         (statePtr->kernStackStart + MACH_BARE_STACK_OFFSET - MACH_SHORT_SIZE);
  486.     statePtr->userState.excStackPtr = excStackPtr;
  487.     statePtr->userState.trapRegs[SP] = (int)excStackPtr;
  488.     excStackPtr->statusReg = 0;
  489.     excStackPtr->pc = (int)entryPoint;
  490.     excStackPtr->vor.stackFormat = MACH_SHORT;
  491.     MachUserReturn(procPtr);
  492.     MachRunUserProc();
  493.     /* THIS DOES NOT RETURN */
  494. }
  495.  
  496.  
  497. /*
  498.  *----------------------------------------------------------------------
  499.  *
  500.  * Mach_ExecUserProc --
  501.  *
  502.  *    Replace the calling user process's image with a new one.
  503.  *
  504.  * Results:
  505.  *    None.
  506.  *
  507.  * Side effects:
  508.  *    Stack pointer set for the process.
  509.  *
  510.  *----------------------------------------------------------------------
  511.  */
  512. void
  513. Mach_ExecUserProc(procPtr, userStackPtr, entryPoint)
  514.     Proc_ControlBlock    *procPtr;        /* Process control block for
  515.                          * process to exec. */
  516.     Address        userStackPtr;    /* Stack pointer for when the
  517.                          * user process resumes 
  518.                          * execution. */
  519.     Address        entryPoint;        /* Where the user process is
  520.                          * to resume execution. */
  521. {
  522.     procPtr->machStatePtr->userState.userStackPtr = userStackPtr;
  523.     Mach_StartUserProc(procPtr, entryPoint);
  524.     /* THIS DOES NOT RETURN */
  525. }
  526.  
  527. /*
  528.  *----------------------------------------------------------------------
  529.  *
  530.  * Mach_FreeState --
  531.  *
  532.  *    Free up the machine state for the given process control block.
  533.  *
  534.  * Results:
  535.  *    None.
  536.  *
  537.  * Side effects:
  538.  *    Free up the kernel stack.
  539.  *
  540.  *----------------------------------------------------------------------
  541.  */
  542. void
  543. Mach_FreeState(procPtr)
  544.     Proc_ControlBlock    *procPtr;    /* Process control block to free
  545.                      * machine state for. */
  546. {
  547.     if (procPtr->machStatePtr->kernStackStart != (Address)NIL) {
  548.     Vm_FreeKernelStack(procPtr->machStatePtr->kernStackStart);
  549.     procPtr->machStatePtr->kernStackStart = (Address)NIL;
  550.     }
  551. }
  552.  
  553.  
  554. /*
  555.  *----------------------------------------------------------------------
  556.  *
  557.  * Mach_CopyState --
  558.  *
  559.  *    Copy the state from the given state structure to the machine
  560.  *    state structure for the destination process control block.  Intended
  561.  *    to be used by the debugger to modify the state.The only fields
  562.  *    that can be modified are the following:
  563.  *
  564.  *        1) user stack pointer
  565.  *        2) all trap registers except for the stack pointer because the
  566.  *           stack pointer in the trap registers is the kernel stack pointer.
  567.  *        3) the PC, VOR and status register in the exception stack.
  568.  *
  569.  * Results:
  570.  *    None.
  571.  *
  572.  * Side effects:
  573.  *    Machine state in the destination process control block is overwritten.
  574.  *
  575.  *----------------------------------------------------------------------
  576.  */ 
  577. void
  578. Mach_CopyState(statePtr, destProcPtr)
  579.     Mach_State        *statePtr;    /* Pointer to state to copy from. */
  580.     Proc_ControlBlock    *destProcPtr;    /* Process control block to copy
  581.                      * state to. */
  582. {
  583.     register    Mach_State    *destStatePtr;
  584.  
  585.     destStatePtr = destProcPtr->machStatePtr;
  586.     destStatePtr->userState.userStackPtr =
  587.                 statePtr->userState.userStackPtr;
  588.     bcopy((Address)statePtr->userState.trapRegs,
  589.           (Address)destStatePtr->userState.trapRegs,
  590.           sizeof(int) * (MACH_NUM_GPRS - 1));
  591. #ifdef sun3
  592.     bcopy((Address)statePtr->userState.trapFpRegs,
  593.           (Address)destStatePtr->userState.trapFpRegs,
  594.           sizeof(statePtr->userState.trapFpRegs));
  595.     bcopy((Address)statePtr->userState.trapFpCtrlRegs,
  596.           (Address)destStatePtr->userState.trapFpCtrlRegs,
  597.           sizeof(statePtr->userState.trapFpCtrlRegs));
  598.     bcopy((Address) &statePtr->userState.trapFpuState,
  599.           (Address) &destStatePtr->userState.trapFpuState,
  600.           sizeof(statePtr->userState.trapFpuState));
  601. #endif
  602.     destStatePtr->userState.excStackPtr->pc = 
  603.                     statePtr->userState.excStackPtr->pc;
  604.     destStatePtr->userState.excStackPtr->statusReg = 
  605.                 statePtr->userState.excStackPtr->statusReg;
  606. }
  607.  
  608.  
  609. /*
  610.  *----------------------------------------------------------------------
  611.  *
  612.  * Mach_GetDebugState --
  613.  *
  614.  *    Extract the appropriate fields from the machine state struct
  615.  *    and store them into the debug struct.
  616.  *
  617.  * Results:
  618.  *    None.
  619.  *
  620.  * Side effects:
  621.  *    Debug struct filled in from machine state struct.
  622.  *
  623.  *----------------------------------------------------------------------
  624.  */ 
  625. void
  626. Mach_GetDebugState(procPtr, debugStatePtr)
  627.     Proc_ControlBlock    *procPtr;
  628.     Proc_DebugState    *debugStatePtr;
  629. {
  630.     register    Mach_State    *machStatePtr;
  631.  
  632.     machStatePtr = procPtr->machStatePtr;
  633.     bcopy((Address)machStatePtr->userState.trapRegs,
  634.           (Address)debugStatePtr->regState.regs,
  635.           sizeof(machStatePtr->userState.trapRegs));
  636.     debugStatePtr->regState.regs[SP] = 
  637.             (int)machStatePtr->userState.userStackPtr;
  638.     debugStatePtr->regState.pc = machStatePtr->userState.excStackPtr->pc;
  639.     debugStatePtr->regState.statusReg  =
  640.             machStatePtr->userState.excStackPtr->statusReg;
  641. }
  642.  
  643.  
  644. /*
  645.  *----------------------------------------------------------------------
  646.  *
  647.  * Mach_SetDebugState --
  648.  *
  649.  *    Extract the appropriate fields from the debug struct
  650.  *    and store them into the machine state struct.
  651.  *
  652.  * Results:
  653.  *    None.
  654.  *
  655.  * Side effects:
  656.  *    Machine state struct filled in from the debug state struct.
  657.  *
  658.  *----------------------------------------------------------------------
  659.  */ 
  660. void
  661. Mach_SetDebugState(procPtr, debugStatePtr)
  662.     Proc_ControlBlock    *procPtr;
  663.     Proc_DebugState    *debugStatePtr;
  664. {
  665.     register    Mach_State    *machStatePtr;
  666.  
  667.     machStatePtr = procPtr->machStatePtr;
  668.     bcopy((Address)debugStatePtr->regState.regs,
  669.           (Address)machStatePtr->userState.trapRegs,
  670.           sizeof(machStatePtr->userState.trapRegs) - sizeof(int));
  671.     machStatePtr->userState.userStackPtr = 
  672.                 (Address)debugStatePtr->regState.regs[SP];
  673.     machStatePtr->userState.excStackPtr->pc = 
  674.                 debugStatePtr->regState.pc;
  675.     if (!(debugStatePtr->regState.statusReg & MACH_SR_SUPSTATE)) {
  676.     machStatePtr->userState.excStackPtr->statusReg = 
  677.                 debugStatePtr->regState.statusReg;
  678.     }
  679. }
  680.  
  681.  
  682.  
  683. /*
  684.  * ----------------------------------------------------------------------------
  685.  *
  686.  * Mach_GetUserStackPtr --
  687.  *
  688.  *    Return the user stack pointer from the machine state struct for the
  689.  *    given process.
  690.  *
  691.  * Results:
  692.  *    The value of the user stack pointer when the process trapped.
  693.  *
  694.  * Side effects:
  695.  *    None.
  696.  *
  697.  * ----------------------------------------------------------------------------
  698.  */
  699. Address
  700. Mach_GetUserStackPtr(procPtr)
  701.     Proc_ControlBlock    *procPtr;
  702. {
  703.     return(procPtr->machStatePtr->userState.userStackPtr);
  704. }
  705.  
  706.  
  707. /*
  708.  *----------------------------------------------------------------------
  709.  *
  710.  * Mach_InitSyscall --
  711.  *
  712.  *    During initialization, this procedure is called once for each
  713.  *    kernel call, in order to set up information used to dispatch
  714.  *    the kernel call.  This procedure must be called once for each
  715.  *    kernel call, in order starting at 0.
  716.  *
  717.  * Results:
  718.  *    None.
  719.  *
  720.  * Side effects:
  721.  *    Initializes the dispatch tables for the kernel call.
  722.  *
  723.  *----------------------------------------------------------------------
  724.  */
  725. void
  726. Mach_InitSyscall(callNum, numArgs, normalHandler, migratedHandler)
  727.     int callNum;            /* Number of the system call. */
  728.     int numArgs;            /* Number of one-word arguments passed
  729.                      * into call on stack. */
  730.     ReturnStatus (*normalHandler)();    /* Procedure to process kernel call
  731.                      * when process isn't migrated. */
  732.     ReturnStatus (*migratedHandler)();    /* Procedure to process kernel call
  733.                      * for migrated processes. */
  734. {
  735.     machMaxSysCall++;
  736.     if (machMaxSysCall != callNum) {
  737.     printf("Warning: out-of-order kernel call initialization, call %d\n",
  738.            callNum);
  739.     }
  740.     if (machMaxSysCall >= MAXCALLS) {
  741.     printf("Mach_InitSyscall: too many kernel calls\n",
  742.            machMaxSysCall);
  743.     machMaxSysCall--;
  744.     return;
  745.     }
  746.     if (numArgs > MAXARGS) {
  747.     printf("Mach_InitSyscall: too many arguments (%d) to kernel call <%d>\n",
  748.         numArgs, callNum);
  749.     numArgs = MAXARGS;
  750.     }
  751.  
  752.     /*
  753.      * MachArgOffsets and machArgDispatch below are used in MachSyscallTrap
  754.      * to do a very quick dispatch to copy arguments from the user stack
  755.      * to the kernel stack.  machArgOffsets is used to locate the first
  756.      * argument on the user's stack, and machArgDispatch is used to branch
  757.      * into the middle of an unwound loop to do the copy.  See the
  758.      * argument-copying code in MachSyscallTrap for more details.
  759.      */
  760.  
  761.     machArgOffsets[machMaxSysCall] = 8 + numArgs*4;
  762.     machArgDispatch[machMaxSysCall] = 
  763.         (16-numArgs)*2 + (Address) MachFetchArgs;
  764.     mach_NormalHandlers[machMaxSysCall] = normalHandler;
  765.     mach_MigratedHandlers[machMaxSysCall] = migratedHandler;
  766. }
  767.  
  768. /*
  769.  * ----------------------------------------------------------------------------
  770.  *
  771.  * Mach_SetHandler --
  772.  *
  773.  *    Put a device driver interrupt handling routine into the autovector.
  774.  *
  775.  * Results:
  776.  *     None.
  777.  *
  778.  * Side effects:
  779.  *     The exception vector table is modified.
  780.  *
  781.  * ----------------------------------------------------------------------------
  782.  */
  783.  
  784. void
  785. Mach_SetHandler(vectorNumber, handler, clientData)
  786.     int vectorNumber;    /* Vector number that the device generates */
  787.     int (*handler)();    /* Interrupt handling procedure */
  788.     ClientData    clientData; /* ClientData for interrupt callback routine. */
  789. {
  790.     int    *vecTablePtr;
  791.     extern int    MachVectoredInterrupt();
  792.     /*
  793.      * Don't let the caller override a vector than can't be generated with
  794.      * an interrupt. Only vectors 24 thru 30 and 64 thru 255 can be 
  795.      * generated.
  796.      */
  797.     if ((vectorNumber < 25) ||
  798.     ((vectorNumber > 30) && (vectorNumber < 64)) || 
  799.     (vectorNumber > 255)) {
  800.     panic("Warning: Bad vector number %d\n",vectorNumber);
  801.     } else {
  802.     machInterruptRoutines[vectorNumber] = handler;
  803.     machInterruptArgs[vectorNumber] = clientData;
  804.     vecTablePtr = (int *) MachGetVBR();
  805.     vecTablePtr[vectorNumber] = (int)MachVectoredInterrupt;
  806.     }
  807. }
  808.  
  809.  
  810. /*
  811.  * ----------------------------------------------------------------------------
  812.  *
  813.  * MachTrap --
  814.  *
  815.  *      The trap handler routine.  This deals with supervisor mode and 
  816.  *    non-supervisor mode traps differently.  The only allowed supervisor
  817.  *    mode traps are a breakpoint trap to force a context switch and a
  818.  *    bus error in the middle of a cross address space copy. All other
  819.  *    traps go into the debugger.  However, all types of user traps are 
  820.  *    processed here, except for system calls, which don't pass through
  821.  *    this procedure unless special action (like a context switch) is
  822.  *    needed at the end of the call.
  823.  *
  824.  * Results:
  825.  *      MACH_KERN_ERROR if the debugger should be called after this routine 
  826.  *    returns, MACH_USER_ERROR if a copy to/from user space caused an 
  827.  *    unrecoverable bus error, and MACH_OK if everything worked out ok.
  828.  *
  829.  * Side effects:
  830.  *      None.
  831.  *
  832.  * ----------------------------------------------------------------------------
  833.  */
  834. int
  835. MachTrap(trapStack)
  836.     Mach_TrapStack    trapStack;    /* The stack at the time of the trap.*/
  837. {
  838.     register    Proc_ControlBlock    *procPtr;
  839.     ReturnStatus            status;
  840.  
  841.     procPtr = Proc_GetActualProc();
  842.     /*
  843.      * Process kernel traps.
  844.      */
  845.     if (trapStack.excStack.statusReg & MACH_SR_SUPSTATE) {
  846.     switch (trapStack.trapType) {
  847.         case MACH_TRACE_TRAP:
  848.         /*
  849.          * If the trace trap occured on a user trap instruction, then
  850.          * the trace trap will be taken on the first instruction of 
  851.          * the trap handler.  When this trace trap occurs,
  852.          * instead of the saved status register being in user mode and 
  853.          * having the trace trap bit set, the status register will 
  854.          * be in kernel mode with no trace trap bit set.
  855.          * In this case we just ignore the trace trap because it 
  856.          * will reoccur when the user process continues.
  857.          */
  858.         if (!(trapStack.excStack.statusReg & MACH_SR_TRACEMODE)) {
  859.             return(MACH_OK);
  860.         }
  861.  
  862.         /*
  863.          * In the normal case enter the debugger with a breakpoint
  864.          * trap.
  865.          */
  866.         return(MACH_KERN_ERROR);
  867.  
  868.         case MACH_BUS_ERROR:
  869.  
  870.         if (trapStack.busErrorReg.timeOut) {
  871.             /*
  872.              * Allow for refresh memory time just like Unix.
  873.              */
  874.             MACH_DELAY(2000);
  875.         }
  876.  
  877.         /*
  878.          * Check to see if is a parity error.
  879.          */
  880.  
  881. #ifndef sun3
  882.         if (trapStack.busErrorReg.parErrU || trapStack.busErrorReg.parErrL) {
  883.             panic("Parity error!!!\n");
  884.             return(MACH_KERN_ERROR);
  885.         }
  886.  
  887.         if (trapStack.busErrorReg.busErr) {
  888.             panic("System bus error\n");
  889.             return(MACH_KERN_ERROR);
  890.         }
  891. #endif
  892.  
  893.         if (procPtr == (Proc_ControlBlock *)NIL) {
  894.             panic("MachTrap: Current process is NIL!! Trap PC 0x%x\n",
  895.                (unsigned) trapStack.excStack.pc);
  896.         }
  897.  
  898.         if (procPtr->genFlags & PROC_USER) {
  899.             Boolean    protError;
  900.             Boolean    copyInProgress = FALSE;
  901.  
  902.             /*
  903.              * A page fault on a user process while executing in
  904.              * the kernel.  This can happen when information is
  905.              * being copied back and forth between kernel and
  906.              * user state (indicated by particular values of the
  907.              * program counter), after a pointer is made accessible by 
  908.              * Vm_MakeAccessible (indicated by numMakeAcc > 0) or
  909.              * after someone did a Mach_Probe() in the kernel and tried
  910.              * to access a user process.
  911.              */
  912.  
  913.             if ((((Address) trapStack.excStack.pc) >=
  914.                 (Address) Vm_CopyIn)
  915.                 && (((Address) trapStack.excStack.pc)
  916.                 < (Address) VmMachCopyEnd)) {
  917.             copyInProgress = TRUE;
  918.             } else if ((((Address) trapStack.excStack.pc)
  919.                 >= (Address) MachFetchArgs2)
  920.                 && (((Address) trapStack.excStack.pc)
  921.                 <= (Address) MachFetchArgsEnd2)) {
  922.             copyInProgress = TRUE;
  923.             } else if ((((Address) trapStack.excStack.pc)
  924.                 >= (Address) MachFetchArgs)
  925.                 && (((Address) trapStack.excStack.pc)
  926.                 <= (Address) MachFetchArgsEnd)) {
  927.             copyInProgress = TRUE;
  928.             } else if ((((Address) trapStack.excStack.pc)
  929.                 >= (Address) MachProbeStart)
  930.                 && (((Address) trapStack.excStack.pc)
  931.                 <= (Address) MachProbeEnd)) {
  932.             return(MACH_USER_ERROR);
  933.             } else if (procPtr->vmPtr->numMakeAcc == 0) {
  934.             return(MACH_KERN_ERROR);
  935.             }
  936.  
  937.             protError = 
  938. #ifdef sun3
  939.                 !trapStack.busErrorReg.pageInvalid;
  940. #else
  941.                 trapStack.busErrorReg.resident;
  942. #endif
  943.             /*
  944.              * Try to fault in the page.
  945.              */
  946.             status = Vm_PageIn(
  947.               (Address)trapStack.excStack.tail.addrBusErr.faultAddr,
  948.                   protError);
  949.             if (status != SUCCESS) {
  950.             if (copyInProgress) {
  951.                 return(MACH_USER_ERROR);
  952.             } else {
  953.                 /*
  954.                  * Real kernel error. 
  955.                  */
  956.                 return(MACH_KERN_ERROR);
  957.             }
  958.             } else {
  959.             return(MACH_OK);
  960.             }
  961.         } else {
  962.             /*
  963.              * Happened to a kernel process.  If the error happen 
  964.              * in Mach_Probe() return MACH_USER_ERROR to force 
  965.              * Mach_Probe() to return FAILURE.
  966.              */
  967.             if ((((Address) trapStack.excStack.pc)
  968.                 >= (Address) MachProbeStart)
  969.               && (((Address) trapStack.excStack.pc)
  970.                 <= (Address) MachProbeEnd)) {
  971.             return(MACH_USER_ERROR);
  972.             } else { 
  973.             return(MACH_KERN_ERROR);
  974.             }
  975.         }
  976.         case MACH_SPURIOUS_INT:
  977.         /*
  978.          * Ignore this for now because otherwise we can't debug mint
  979.          */
  980.         if (!dbg_BeingDebugged) {
  981.             printf("MachTrap: Spurious interrupt\n");
  982.         }
  983.         return(MACH_OK);
  984.  
  985.         default:
  986.         return(MACH_KERN_ERROR);
  987.     }
  988.     } 
  989.  
  990.     /*
  991.      * Process user traps.  
  992.      */
  993.  
  994.     /* 
  995.      * Take a context switch if one is pending for this process.
  996.      */
  997.  
  998.     if (procPtr->schedFlags & SCHED_CONTEXT_SWITCH_PENDING) {
  999.     Sched_LockAndSwitch();
  1000.     }
  1001.     /*
  1002.      * Now clear out the trace trap bit out of the status register.  This is
  1003.      * a precaution to take care of cases such as when a bus error occurs on 
  1004.      * the instruction that we are trying to trace such that the trace trap bit
  1005.      * is set but we didn't get a trace trap exception.
  1006.      */
  1007.     trapStack.excStack.statusReg &= ~MACH_SR_TRACEMODE;
  1008.  
  1009.     switch (trapStack.trapType) {
  1010.     case MACH_BUS_ERROR: {
  1011.         Boolean    protError;
  1012.         if (trapStack.busErrorReg.timeOut) {
  1013.         /*
  1014.          * Allow for refresh memory time just like Unix.
  1015.          */
  1016.  
  1017.         MACH_DELAY(2000);
  1018.         }
  1019.  
  1020.         /*
  1021.          * Check for parity error.
  1022.          */
  1023.  
  1024. #ifndef sun3
  1025.         if (trapStack.busErrorReg.parErrU || trapStack.busErrorReg.parErrL) {
  1026.         panic("Parity error!!!\n");
  1027.         return(MACH_KERN_ERROR);
  1028.         }
  1029. #endif
  1030.  
  1031.         /*
  1032.          * Take a page fault. It is assumed that if the resident bit
  1033.          * is set in the bus error register then this is a protection
  1034.          * error.
  1035.          */
  1036.     protError =
  1037. #ifdef sun3
  1038.             !trapStack.busErrorReg.pageInvalid;
  1039. #else
  1040.             trapStack.busErrorReg.resident;
  1041. #endif
  1042.     if (Vm_PageIn((Address)trapStack.excStack.tail.addrBusErr.faultAddr, 
  1043.               protError) != SUCCESS) {
  1044.         printf(
  1045.             "MachTrap: Bus error in user proc %X, PC = %x, addr = %x BR Reg %x\n",
  1046.                 procPtr->processID, 
  1047.                 trapStack.excStack.pc,
  1048.                 trapStack.excStack.tail.addrBusErr.faultAddr,
  1049.                 *(int *)&trapStack.busErrorReg);
  1050.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  1051.                 procPtr->processID, FALSE,
  1052.             (Address)trapStack.excStack.tail.addrBusErr.faultAddr);
  1053.         }
  1054.         break;
  1055.     }
  1056.     case MACH_UNIX_SYSCALL_TRAP:
  1057.     case MACH_SYSCALL_TRAP:
  1058.         /*
  1059.          * It used to be that all system calls passed through here, but
  1060.          * the code was optimized to avoid calling either this procedure
  1061.          * or Sys_SysCall in the normal case.  Control only passes through
  1062.          * here if, at the end of a system call, it's discovered that
  1063.          * special action must be taken.  The call has already been
  1064.          * executed by the time things arrive here.  This code does
  1065.          * nothing... the action will all be taken by the call to
  1066.          * MachUserReturn below.
  1067.          */
  1068.  
  1069.         break;
  1070.         
  1071.     case MACH_BRKPT_TRAP:
  1072.         Proc_Lock(procPtr);
  1073.         if (procPtr->genFlags & PROC_DEBUG_ON_EXEC) {
  1074.             procPtr->genFlags &= ~PROC_DEBUG_ON_EXEC;
  1075.         (void) Sig_SendProc(procPtr, SIG_DEBUG, SIG_NO_CODE,
  1076.             (Address)0);
  1077.         } else {
  1078.         (void) Sig_SendProc(procPtr, SIG_BREAKPOINT, SIG_NO_CODE,
  1079.             (Address)0);
  1080.         }
  1081.         Proc_Unlock(procPtr);
  1082.         break;
  1083.  
  1084.     case MACH_SIG_RET_TRAP: {
  1085.         /*
  1086.          * We got a return from signal trap.
  1087.          */
  1088.         ReturnFromSigHandler(procPtr);
  1089.         return(MACH_SIG_RETURN);
  1090.     }
  1091.  
  1092.     case MACH_ADDRESS_ERROR:
  1093.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ADDR_ERROR,
  1094.                 procPtr->processID, FALSE,
  1095.              (Address)trapStack.excStack.tail.addrBusErr.faultAddr);
  1096.         break;
  1097.     case MACH_ILLEGAL_INST:
  1098.         printf("Illegal instruction in %x at %x\n", procPtr->processID,
  1099.             trapStack.excStack.pc);
  1100.         (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE,
  1101.                 procPtr->processID, FALSE,
  1102.                (Address)trapStack.excStack.pc);
  1103.         break;
  1104.     case MACH_ZERO_DIV:
  1105.         (void) Sig_Send(SIG_ARITH_FAULT, SIG_ZERO_DIV,
  1106.                 procPtr->processID, FALSE,
  1107.                  (Address)trapStack.excStack.pc);
  1108.         break;
  1109.     case MACH_CHK_INST:
  1110.         (void) Sig_Send(SIG_ILL_INST, SIG_CHK,
  1111.                 procPtr->processID, FALSE,
  1112.                  (Address)trapStack.excStack.pc);
  1113.         break;
  1114.     case MACH_TRAPV:
  1115.         (void) Sig_Send(SIG_ILL_INST, SIG_TRAPV,
  1116.                 procPtr->processID, FALSE,
  1117.                  (Address)trapStack.excStack.pc);
  1118.         break;
  1119.     case MACH_PRIV_VIOLATION:
  1120.         (void) Sig_Send(SIG_ILL_INST, SIG_PRIV_INST,
  1121.                 procPtr->processID, FALSE,
  1122.                  (Address)trapStack.excStack.pc);
  1123.         break;
  1124.     case MACH_TRACE_TRAP: 
  1125.         /*
  1126.          * Involuntary context switch trace traps have already been taken
  1127.          * care of above.  Here the only time we pay attention to a
  1128.          * trace trap is if the debugger is trying to single step the 
  1129.          * user process.
  1130.          */
  1131.         if (procPtr->genFlags & PROC_SINGLE_STEP_FLAG) {
  1132.         procPtr->genFlags &= ~PROC_SINGLE_STEP_FLAG;
  1133.         (void) Sig_Send(SIG_TRACE_TRAP, SIG_NO_CODE,
  1134.                 procPtr->processID, FALSE,
  1135.                  (Address)trapStack.excStack.pc);
  1136.         }
  1137.         break;
  1138.  
  1139.     case MACH_EMU1010:
  1140.         (void) Sig_Send(SIG_ILL_INST, SIG_EMU1010,
  1141.                 procPtr->processID, FALSE,
  1142.                  (Address)trapStack.excStack.pc);
  1143.         break;
  1144.     case MACH_EMU1111:
  1145.         (void) Sig_Send(SIG_ILL_INST, SIG_EMU1111,
  1146.                 procPtr->processID, FALSE,
  1147.                  (Address)trapStack.excStack.pc);
  1148.         break;
  1149.     case MACH_BAD_TRAP:
  1150.         (void) Sig_Send(SIG_ILL_INST, SIG_BAD_TRAP,
  1151.                 procPtr->processID, FALSE,
  1152.                  (Address)trapStack.excStack.pc);
  1153.         break;
  1154. #ifdef sun3
  1155.     case MACH_FP_UNORDERED_COND:
  1156.         (void) Sig_Send(SIG_ARITH_FAULT, SIG_FP_UNORDERED_COND,
  1157.                 procPtr->processID, FALSE,
  1158.                  (Address)trapStack.excStack.pc);
  1159.     case MACH_FP_INEXACT_RESULT:
  1160.         (void) Sig_Send(SIG_ARITH_FAULT, SIG_FP_INEXACT_RESULT,
  1161.                 procPtr->processID, FALSE,
  1162.                  (Address)trapStack.excStack.pc);
  1163.     case MACH_FP_ZERO_DIV:
  1164.         (void) Sig_Send(SIG_ARITH_FAULT, SIG_FP_ZERO_DIV,
  1165.                 procPtr->processID, FALSE,
  1166.                  (Address)trapStack.excStack.pc);
  1167.     case MACH_FP_UNDERFLOW:
  1168.         (void) Sig_Send(SIG_ARITH_FAULT, SIG_FP_UNDERFLOW,
  1169.                 procPtr->processID, FALSE,
  1170.                  (Address)trapStack.excStack.pc);
  1171.     case MACH_FP_OPERAND_ERROR:
  1172.         (void) Sig_Send(SIG_ARITH_FAULT, SIG_FP_OPERAND_ERROR,
  1173.                 procPtr->processID, FALSE,
  1174.                  (Address)trapStack.excStack.pc);
  1175.     case MACH_FP_OVERFLOW:
  1176.         (void) Sig_Send(SIG_ARITH_FAULT, SIG_FP_OVERFLOW,
  1177.                 procPtr->processID, FALSE,
  1178.                  (Address)trapStack.excStack.pc);
  1179.     case MACH_FP_NAN:
  1180.         (void) Sig_Send(SIG_ARITH_FAULT, SIG_FP_NAN,
  1181.                 procPtr->processID, FALSE,
  1182.                  (Address)trapStack.excStack.pc);
  1183. #endif
  1184.     default:
  1185.         return(MACH_KERN_ERROR);
  1186.     } 
  1187.  
  1188.     MachUserReturn(procPtr);
  1189.     return(MACH_OK);
  1190. }
  1191.  
  1192.  
  1193. /*
  1194.  * ----------------------------------------------------------------------------
  1195.  *
  1196.  * MachUserReturn --
  1197.  *
  1198.  *      Take the proper action to return from a user exception.
  1199.  *
  1200.  * Results:
  1201.  *      None.
  1202.  *
  1203.  * Side effects:
  1204.  *      Interrupts disabled.
  1205.  *
  1206.  * ----------------------------------------------------------------------------
  1207.  */
  1208. void
  1209. MachUserReturn(procPtr)
  1210.     register    Proc_ControlBlock    *procPtr;
  1211. {
  1212.     SignalStack            sigStack;
  1213.     Address            pc;
  1214.     int                restarted=0;
  1215.  
  1216.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1217.         procPtr->unixProgress != PROC_PROGRESS_UNIX && debugProcStubs) {
  1218.     printf("UnixProgress = %d entering MachUserReturn\n",
  1219.         procPtr->unixProgress);
  1220.     }
  1221.  
  1222.     if (procPtr->Prof_Scale != 0 && procPtr->Prof_PC != 0) {
  1223.     Prof_RecordPC(procPtr);
  1224.     }
  1225.  
  1226.     /* 
  1227.      * Take a context switch if one is pending for this process.
  1228.      */
  1229.     if (procPtr->schedFlags & SCHED_CONTEXT_SWITCH_PENDING) {
  1230.     Sched_LockAndSwitch();
  1231.     }
  1232.  
  1233.     /*
  1234.      * Check for signals.  Interrupts are disabled because we have to 
  1235.      * make sure that we don't miss a signal.  Interrupts will be reenabled
  1236.      * automatically upon the rte.  
  1237.      */
  1238.     while (TRUE) {
  1239.     /*
  1240.      * Disable interrupts.  Note that we don't use the DISABLE_INTR macro
  1241.      * because it increments the nesting depth of interrupts which we don't
  1242.      * want because there is an implicit enable interrupts on rte.
  1243.      */
  1244.     Mach_DisableIntr();
  1245.     if (!Sig_Pending(procPtr)) {
  1246.         break;
  1247.     }
  1248.     Mach_EnableIntr();
  1249.     sigStack.sigStack.contextPtr = &sigStack.sigContext;
  1250.     if (procPtr->unixProgress == PROC_PROGRESS_RESTART ||
  1251.         procPtr->unixProgress > 0) {
  1252.         /*
  1253.          * If we received a normal signal, we want to restart
  1254.          * the system call when we leave.
  1255.          * If we received a migrate signal, we will get here on
  1256.          * the new machine.
  1257.          * We must also ensure that the argument registers are the
  1258.          * same as when we came in.
  1259.          */
  1260.         restarted = 1;
  1261.         if (debugProcStubs) {
  1262.         printf("Restarting system call with progress %d\n",
  1263.             procPtr->unixProgress);
  1264.         }
  1265.         procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1266.     }
  1267.     if (Sig_Handle(procPtr, &sigStack.sigStack, &pc)) {
  1268.         if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX) {
  1269.         procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1270.         }
  1271.         SetupSigHandler(procPtr, &sigStack, pc);
  1272.         Mach_DisableIntr();
  1273.         break;
  1274.     } else {
  1275.         if (procPtr->unixProgress == PROC_PROGRESS_MIG_RESTART ||
  1276.             procPtr->unixProgress == PROC_PROGRESS_RESTART) {
  1277.         restarted = 1;
  1278.         if (debugProcStubs) {
  1279.             printf("No signal action, so we restarted call\n");
  1280.         }
  1281.         procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1282.         } else if (restarted && debugProcStubs) {
  1283.         printf("No signal, yet we restarted system call!\n");
  1284.         }
  1285.     }
  1286.     }
  1287.  
  1288.     if ((procPtr->genFlags & PROC_SINGLE_STEP_FLAG) ||
  1289.     (procPtr->schedFlags & SCHED_CONTEXT_SWITCH_PENDING)) {
  1290.     /*
  1291.      * Set the trace trap bit if we are supposed to single-step this
  1292.      * process or a context switch is pending.  We check for a context
  1293.      * switch pending here even though we just checked above just in
  1294.      * case we got preempted while dealing with signals.
  1295.      */
  1296.     procPtr->machStatePtr->userState.excStackPtr->statusReg |= 
  1297.                             MACH_SR_TRACEMODE;
  1298.     }
  1299.  
  1300.     /*
  1301.      * It is possible for Sig_Handle to mask the migration signal
  1302.      * if a process is not in a state where it can be migrated.
  1303.      * As soon as we return to user mode, though, we will allow migration.
  1304.      */
  1305.     Sig_AllowMigration(procPtr);
  1306.  
  1307.     if (restarted) {
  1308.     if (debugProcStubs) {
  1309.         printf("Moving the PC to restart the system call\n");
  1310.     }
  1311.     procPtr->machStatePtr->userState.excStackPtr->pc -= 4;
  1312.     }
  1313.  
  1314.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1315.             procPtr->unixProgress != PROC_PROGRESS_UNIX && debugProcStubs) {
  1316.         printf("UnixProgress = %d leaving MachUserReturn\n",
  1317.                 procPtr->unixProgress);
  1318.     }
  1319.  
  1320. }
  1321.  
  1322.  
  1323. /*
  1324.  * ----------------------------------------------------------------------------
  1325.  *
  1326.  * Routines to set up and return from signal handlers.
  1327.  *
  1328.  * In order to call a handler four things must be done:
  1329.  *
  1330.  *    1) The current state of the process must be saved so that when
  1331.  *       the handler returns a normal return to user space can occur.
  1332.  *    2) The user stack must be set up so that the signal number and the
  1333.  *       the signal code are passed to the handler.
  1334.  *    3) Things must be set up so that when the handler returns it returns
  1335.  *       back into the kernel so that state can be cleaned up.
  1336.  *    4) The trap stack that was created when the kernel was entered and is
  1337.  *       used to return a process to user space must be modified so that
  1338.  *       the signal handler is called instead of executing the
  1339.  *       normal return.
  1340.  *
  1341.  * The last one is done by simply changing the program counter where the
  1342.  * user process will execute on return to be the address of the signal
  1343.  * handler and the user stack pointer to point to the proper place on
  1344.  * the user stack.  The first three of these are accomplished by 
  1345.  * setting up the user stack properly.  The top entry on the stack is the
  1346.  * return address where the handler will start executing upon return.  But 
  1347.  * this is just the address of a trap instruction that is stored on the stack
  1348.  * below.  Thus when a handler returns it will execute a trap instruction 
  1349.  * and drop back into the kernel. 
  1350.  */
  1351.  
  1352.  
  1353. /*
  1354.  * ----------------------------------------------------------------------------
  1355.  *
  1356.  * SetupSigHandler --
  1357.  *
  1358.  *      Save machine state on the users stack and set up the exception stack
  1359.  *    so that the user will call the signal handler on return. In order to
  1360.  * Results:
  1361.  *      None.
  1362.  *
  1363.  * Side effects:
  1364.  *      Signal stack set up and saved.
  1365.  *
  1366.  * ----------------------------------------------------------------------------
  1367.  */
  1368. static void
  1369. SetupSigHandler(procPtr, sigStackPtr, pc)
  1370.     register    Proc_ControlBlock    *procPtr;
  1371.     register    SignalStack        *sigStackPtr;
  1372.     Address                pc;
  1373. {
  1374.     register    Mach_State    *statePtr;
  1375.     Address            usp;
  1376.     int                excStackSize;
  1377.     Mach_ExcStack        *excStackPtr;
  1378.     struct UnixSignalStack    unixSigStack;
  1379.     int                unixSignal;
  1380.  
  1381.     statePtr = procPtr->machStatePtr;
  1382.     excStackSize = Mach_GetExcStackSize(statePtr->userState.excStackPtr);
  1383.  
  1384.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX) {
  1385.     usp = (Address)statePtr->userState.userStackPtr -
  1386.         sizeof(UnixSignalStack);
  1387.     if (Compat_SpriteSignalToUnix(sigStackPtr->sigStack.sigNum, &unixSignal)
  1388.         != SUCCESS) {
  1389.         printf("Signal %d invalid in SetupSigHandler\n",
  1390.             sigStackPtr->sigStack.sigNum);
  1391.         return;
  1392.     }
  1393.     if (debugProcStubs) {
  1394.         printf("Unix signal %d(%d) to %x\n", unixSignal,
  1395.             sigStackPtr->sigStack.sigNum, procPtr->processID);
  1396.     }
  1397.     unixSigStack.sigNum = unixSignal;
  1398.     unixSigStack.sigCode = sigStackPtr->sigStack.sigCode;
  1399.     unixSigStack.sigContextPtr = (struct sigcontext *)(usp + 4*sizeof(int));
  1400.     unixSigStack.sigAddr = sigStackPtr->sigStack.sigAddr;
  1401.     unixSigStack.sigContext.sc_onstack = 0;
  1402.     unixSigStack.sigContext.sc_mask = 0;
  1403.     unixSigStack.sigContext.sc_sp = (int) statePtr->userState.userStackPtr;
  1404.     unixSigStack.sigContext.sc_pc =
  1405.         (int) statePtr->userState.excStackPtr->pc;
  1406.     unixSigStack.sigContext.sc_ps =
  1407.         (int) statePtr->userState.excStackPtr->statusReg;
  1408.     if (debugProcStubs) {
  1409.         printf("sp = %x, pc = %x, ps = %x, len = %d to %x, exPc = %x\n",
  1410.             statePtr->userState.userStackPtr, pc,
  1411.             unixSigStack.sigContext.sc_ps, sizeof(UnixSignalStack),
  1412.             (Address)usp, statePtr->userState.excStackPtr->pc);
  1413.     }
  1414.     /*
  1415.      * Copy the stack out to user space.
  1416.      */
  1417.     if (Vm_CopyOut(sizeof(UnixSignalStack), (Address)&unixSigStack, 
  1418.                 (Address)usp) != SUCCESS) {
  1419.         printf("Warning: HandleSig: No room on stack for signal, PID=%x.\n",
  1420.               procPtr->processID);
  1421.         Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1422.     }
  1423.     } else {
  1424.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1425.         debugProcStubs) {
  1426.         printf("Warning: process %x has unixProgress = %x\n",
  1427.             procPtr->processID, procPtr->unixProgress);
  1428.     }
  1429.     usp = statePtr->userState.userStackPtr - sizeof(SignalStack);
  1430.     sigStackPtr->sigStack.contextPtr =
  1431.         (Sig_Context *)(usp + (unsigned int)(&sigStackPtr->sigContext) -
  1432.                   (unsigned int)sigStackPtr);
  1433.     /*
  1434.      * We put the instruction TRAP 2 in trapInst, and then set
  1435.      * the return address to point to that instruction.
  1436.      * TRAP 2 does a ReturnFromSigHandler.
  1437.      */
  1438.     sigStackPtr->sigContext.machContext.trapInst = 0x4e424e42;
  1439.     sigStackPtr->retAddr =
  1440.         usp + (unsigned int)(&sigStackPtr->sigContext.machContext.trapInst) -
  1441.           (unsigned int)sigStackPtr;
  1442.     /*
  1443.      * Copy the exception stack onto the signal stack.
  1444.      */
  1445.     bcopy((Address)statePtr->userState.excStackPtr,
  1446.           (Address)&(sigStackPtr->sigContext.machContext.excStack),
  1447.           excStackSize);
  1448.     /*
  1449.      * Copy the user state onto the signal stack.
  1450.      */
  1451.     bcopy((Address)&statePtr->userState,
  1452.           (Address)&(sigStackPtr->sigContext.machContext.userState),
  1453.           sizeof(Mach_UserState));
  1454.     /*
  1455.      * Copy the stack out to user space.
  1456.      */
  1457.     if (Vm_CopyOut(sizeof(SignalStack), (Address)sigStackPtr, 
  1458.                 (Address)usp) != SUCCESS) {
  1459.         printf("Warning: HandleSig: No room on stack for signal, PID=%x.\n",
  1460.               procPtr->processID);
  1461.         Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1462.     }
  1463.     }
  1464.     /*
  1465.      * We need to make a short stack to allow the process to start executing.
  1466.      * The current exception stack is at least as big, maybe bigger than we
  1467.      * need.  Since we saved the true exception stack above, we can just
  1468.      * overwrite the current stack with a short stack and point the stack
  1469.      * pointer at it.
  1470.      */
  1471.     if (statePtr->userState.excStackPtr !=
  1472.             (Mach_ExcStack *)statePtr->userState.trapRegs[SP]) {
  1473.     panic("Mach_HandleSig: SP != excStackPtr\n");
  1474.     }
  1475.     statePtr->userState.userStackPtr = usp;
  1476.     excStackPtr = (Mach_ExcStack *) ((Address)statePtr->userState.excStackPtr + 
  1477.                      excStackSize - MACH_SHORT_SIZE);
  1478.     statePtr->userState.trapRegs[SP] = (int)excStackPtr;
  1479.     excStackPtr->statusReg = 0;
  1480.     excStackPtr->vor.stackFormat = MACH_SHORT;
  1481.     excStackPtr->pc = (int)pc;
  1482. }
  1483.  
  1484.  
  1485. /*
  1486.  * ----------------------------------------------------------------------------
  1487.  *
  1488.  * ReturnFromSigHandler --
  1489.  *
  1490.  *      Process a return from a signal handler.
  1491.  *    
  1492.  * Results:
  1493.  *      None.
  1494.  *
  1495.  * Side effects:
  1496.  *      Signal stack struct and size filled in the machine struct for the
  1497.  *    given process.
  1498.  *
  1499.  * ----------------------------------------------------------------------------
  1500.  */
  1501. static void
  1502. ReturnFromSigHandler(procPtr)
  1503.     register    Proc_ControlBlock    *procPtr;
  1504. {
  1505.     register    Mach_State    *statePtr;
  1506.     int                curSize;
  1507.     int                oldSize;
  1508.     SignalStack            sigStack;
  1509.  
  1510.     statePtr = procPtr->machStatePtr;
  1511.     if (procPtr->unixProgress == PROC_PROGRESS_UNIX) {
  1512.     /*
  1513.      * Unix dynamic linking does a trap#2 for no apparent reason.
  1514.      */
  1515.     return;
  1516.     }
  1517.     /*
  1518.      * Copy the signal stack in.
  1519.      */
  1520.     if (Vm_CopyIn(sizeof(Sig_Stack) + sizeof(Sig_Context),
  1521.           (Address) (statePtr->userState.userStackPtr), 
  1522.           (Address) &sigStack.sigStack) != SUCCESS) {
  1523.     printf("%s Mach_Code: Stack too small to extract trap info, PID=%x.\n",
  1524.         "Warning:", procPtr->processID);
  1525.     Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1526.     }
  1527.     sigStack.sigStack.contextPtr = &sigStack.sigContext;
  1528.     /*
  1529.      * Take the proper action on return from a signal.
  1530.      */
  1531.     Sig_Return(procPtr, &sigStack.sigStack);
  1532.     /*
  1533.      * Restore user state.  Be careful not to clobber the stack
  1534.      * pointer.
  1535.      */
  1536.     statePtr->userState.userStackPtr = 
  1537.             sigStack.sigContext.machContext.userState.userStackPtr;
  1538.     bcopy((Address)sigStack.sigContext.machContext.userState.trapRegs,
  1539.           (Address)statePtr->userState.trapRegs,
  1540.           sizeof(int) * (MACH_NUM_GPRS - 1));
  1541. #ifdef sun3
  1542.     bcopy((Address)sigStack.sigContext.machContext.userState.trapFpRegs,
  1543.           (Address)statePtr->userState.trapFpRegs,
  1544.           sizeof(statePtr->userState.trapFpRegs));
  1545.     bcopy((Address)sigStack.sigContext.machContext.userState.trapFpCtrlRegs,
  1546.           (Address)statePtr->userState.trapFpCtrlRegs,
  1547.           sizeof(statePtr->userState.trapFpCtrlRegs));
  1548.     bcopy((Address) &sigStack.sigContext.machContext.userState.trapFpuState,
  1549.           (Address) &statePtr->userState.trapFpuState,
  1550.           sizeof(statePtr->userState.trapFpuState));
  1551. #endif
  1552.  
  1553.     /*
  1554.      * Verify that the exception stack is OK.
  1555.      */
  1556.     curSize = Mach_GetExcStackSize(statePtr->userState.excStackPtr);
  1557.     oldSize = Mach_GetExcStackSize(&sigStack.sigContext.machContext.excStack);
  1558.     if (oldSize == -1) {
  1559.     printf("Mach_Code: Bad signal stack type.\n");
  1560.     Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1561.     }
  1562.     if (sigStack.sigContext.machContext.excStack.statusReg & MACH_SR_SUPSTATE) {
  1563.     printf("Mach_Code: User set kernel bit on signal stack\n");
  1564.     Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1565.     }
  1566.     /*
  1567.      * Copy the exception stack in.
  1568.      */
  1569.     bcopy((Address)&sigStack.sigContext.machContext.excStack,
  1570.           (Address)&statePtr->sigExcStack, oldSize);
  1571.     statePtr->sigExcStackSize = oldSize;
  1572.     /*
  1573.      * Set the restored stack pointer to point to where the
  1574.      * old exception stack is to be restored to.
  1575.      */
  1576.     statePtr->userState.trapRegs[SP] += curSize - oldSize;
  1577. }
  1578.  
  1579.  
  1580. /*
  1581.  * ----------------------------------------------------------------------------
  1582.  *
  1583.  * Mach_GetExcStackSize --
  1584.  *
  1585.  *      Return the size of the trap stack.  This can vary depending on whether
  1586.  *    are on a Sun-3 or a Sun-2.
  1587.  *
  1588.  * Results:
  1589.  *      Trap stack size.
  1590.  *
  1591.  * Side effects:
  1592.  *      None.
  1593.  *
  1594.  * ----------------------------------------------------------------------------
  1595.  */
  1596. int
  1597. Mach_GetExcStackSize(excStackPtr)
  1598.     Mach_ExcStack    *excStackPtr;
  1599. {
  1600.     switch (excStackPtr->vor.stackFormat) {
  1601.     case MACH_SHORT:
  1602.         return(MACH_SHORT_SIZE);
  1603.     case MACH_THROWAWAY:
  1604.         return(MACH_THROWAWAY_SIZE);
  1605.     case MACH_INST_EXCEPT:
  1606.         return(MACH_INST_EXCEPT_SIZE);
  1607.     case MACH_MC68010_BUS_FAULT:
  1608.         return(MACH_MC68010_BUS_FAULT_SIZE);
  1609.     case MACH_COPROC_MID_INSTR:
  1610.         return(MACH_COPROC_MID_INSTR_SIZE);
  1611.     case MACH_SHORT_BUS_FAULT:
  1612.         return(MACH_SHORT_BUS_FAULT_SIZE);
  1613.     case MACH_LONG_BUS_FAULT:
  1614.         return(MACH_LONG_BUS_FAULT_SIZE);
  1615.     default:
  1616.         printf("Warning: Mach_GetTrapStackSize: Bad stack format.\n");
  1617.         return(-1);
  1618.     }
  1619. }
  1620.  
  1621.  
  1622. /*
  1623.  * ----------------------------------------------------------------------------
  1624.  *
  1625.  * Mach_ProcessorState --
  1626.  *
  1627.  *    Determines what state the processor is in.
  1628.  *
  1629.  * Results:
  1630.  *    MACH_USER    if was at user level
  1631.  *    MACH_KERNEL    if was at kernel level
  1632.  *
  1633.  * Side effects:
  1634.  *    None.
  1635.  *
  1636.  * ----------------------------------------------------------------------------
  1637.  */
  1638. /*ARGSUSED*/
  1639. Mach_ProcessorStates 
  1640. Mach_ProcessorState(processor)
  1641.     int processor;    /* processor number for which info is requested */
  1642. {
  1643.     if (mach_KernelMode) {
  1644.     return(MACH_KERNEL);
  1645.     } else {
  1646.     return(MACH_USER);
  1647.     }
  1648. }
  1649.  
  1650.  
  1651. /*
  1652.  * ----------------------------------------------------------------------------
  1653.  *
  1654.  * Mach_GetMachineArch --
  1655.  *
  1656.  *    Return the machine architecture (SYS_SUN2 or SYS_SUN3).
  1657.  *
  1658.  * Results:
  1659.  *    The machine architecture.
  1660.  *
  1661.  * Side effects:
  1662.  *    None.
  1663.  *
  1664.  * ----------------------------------------------------------------------------
  1665.  */
  1666. int
  1667. Mach_GetMachineArch()
  1668. {
  1669. #       ifdef sun2
  1670.     return SYS_SUN2;
  1671. #       endif sun2
  1672.  
  1673. #       ifdef sun3
  1674.     return SYS_SUN3;
  1675. #       endif sun3
  1676. }
  1677.  
  1678. /*
  1679.  * ----------------------------------------------------------------------------
  1680.  *
  1681.  *  Mach_CheckSpecialHandling--
  1682.  *
  1683.  *    Forces a processor to check the special handling flag of a process.
  1684.  *    This should only be called on a multiprocessor.
  1685.  *
  1686.  * Results:
  1687.  *    None.
  1688.  *
  1689.  * Side effects:
  1690.  *    None.
  1691.  *
  1692.  * ----------------------------------------------------------------------------
  1693.  */
  1694. void
  1695. Mach_CheckSpecialHandling(pnum)
  1696.     int        pnum;        /* Processor number. */
  1697. {
  1698.     panic("Mach_CheckSpecialHandling called for processor %d\n",pnum);
  1699. }
  1700.  
  1701.  
  1702. /*
  1703.  *----------------------------------------------------------------------
  1704.  *
  1705.  * Mach_GetNumProcessors() --
  1706.  *
  1707.  *    Return the number of processors in the system.  NOTE: This should
  1708.  *    really be in a machine-independent area of the mach module.  Note
  1709.  *    further: if this is used only as a system call, it should return
  1710.  *    a ReturnStatus!
  1711.  *
  1712.  * Results:
  1713.  *    The number of processors is returned.  
  1714.  *
  1715.  * Side effects:
  1716.  *    None
  1717.  *
  1718.  *----------------------------------------------------------------------
  1719.  */
  1720.  
  1721. int
  1722. Mach_GetNumProcessors()
  1723. {
  1724.     return (mach_NumProcessors);
  1725. }
  1726.  
  1727.  
  1728. /*
  1729.  *----------------------------------------------------------------------
  1730.  *
  1731.  * Mach_GetBootArgs --
  1732.  *
  1733.  *    Returns the arguments out of the boot parameter structure. 
  1734.  *
  1735.  * Results:
  1736.  *    Number of elements returned in argv.
  1737.  *
  1738.  * Side effects:
  1739.  *    None.
  1740.  *
  1741.  *----------------------------------------------------------------------
  1742.  */
  1743.  
  1744. int
  1745. Mach_GetBootArgs(argc, bufferSize, argv, buffer)
  1746.     int    argc;            /* Number of elements in argv */
  1747.     int    bufferSize;        /* Size of buffer */
  1748.     char    **argv;            /* Ptr to array of arg pointers */
  1749.     char    *buffer;        /* Storage for arguments */
  1750. {
  1751.     int        i;
  1752.     int        offset;
  1753.  
  1754.     bcopy(machMonBootParam.strings, buffer, 
  1755.       (bufferSize < 100) ? bufferSize : 100);
  1756.     offset = (int) machMonBootParam.strings - (int) buffer;
  1757.     for(i = 0; i < argc; i++) {
  1758.     if (machMonBootParam.argPtr[i] == (char *) 0 ||
  1759.         machMonBootParam.argPtr[i] == (char *) NIL) {
  1760.         break;
  1761.     }
  1762.     argv[i] = (char *) (machMonBootParam.argPtr[i] - (char *) offset);
  1763.     }
  1764.     return i;
  1765. }
  1766.  
  1767.  
  1768. /*
  1769.  *----------------------------------------------------------------------
  1770.  *
  1771.  * Mach_SigreturnStub --
  1772.  *
  1773.  *    Procedure to map from Unix sigreturn system call to Sprite.
  1774.  *    This is used for returning from longjmps and signals.
  1775.  *
  1776.  * Results:
  1777.  *    Error code is returned upon error.  Otherwise SUCCESS is returned.
  1778.  *
  1779.  * Side effects:
  1780.  *    Changes the stack, pc, etc. to the specified values.
  1781.  *
  1782.  *----------------------------------------------------------------------
  1783.  */
  1784. int
  1785. Mach_SigreturnStub()
  1786. {
  1787.  
  1788.     Proc_ControlBlock *procPtr = Proc_GetActualProc();
  1789.     Mach_ExcStack *excStackPtr;
  1790.     int excStackSize;
  1791.     int bufVals[5];
  1792.     int *jmpBuf;
  1793.  
  1794.     Vm_CopyIn(sizeof(int), procPtr->machStatePtr->userState.userStackPtr,
  1795.         (Address)&jmpBuf);
  1796.     if (Vm_CopyIn(5*sizeof(int), (Address)jmpBuf, (Address)bufVals) !=
  1797.         SUCCESS) {
  1798.     printf("JmpBuf copy in failure\n");
  1799.     return -1;
  1800.     }
  1801.     if (Sig_SigsetmaskStub(bufVals[1])<0) {
  1802.     printf("Sig_SigsetmaskStub error in Sigreturn on %x\n", bufVals[1]);
  1803.     }
  1804.     if (debugProcStubs) {
  1805.     printf("saved usp = %x, SP= %x, exSp = %x\n",
  1806.         procPtr->machStatePtr->userState.userStackPtr, 
  1807.         procPtr->machStatePtr->userState.trapRegs[SP],
  1808.         procPtr->machStatePtr->userState.excStackPtr);
  1809.     printf("Mach_SigreturnStub(%x from %x): %x, %x, %x, %x, %x\n", jmpBuf,
  1810.         procPtr->machStatePtr->userState.userStackPtr,
  1811.         bufVals[0], bufVals[1],
  1812.         bufVals[2], bufVals[3], bufVals[4]);
  1813.     }
  1814.     procPtr->machStatePtr->userState.userStackPtr = (Address)bufVals[2];
  1815.  
  1816.     /*
  1817.      * We need to make a short stack to allow the process to start executing.
  1818.      * The current exception stack is at least as big, maybe bigger than we
  1819.      * need.  Since we saved the true exception stack above, we can just
  1820.      * overwrite the current stack with a short stack and point the stack
  1821.      * pointer at it.
  1822.      */
  1823.     excStackSize = Mach_GetExcStackSize(procPtr->machStatePtr->
  1824.         userState.excStackPtr);
  1825.     excStackPtr = (Mach_ExcStack *) ((Address)procPtr->machStatePtr
  1826.         ->userState.excStackPtr + excStackSize - MACH_SHORT_SIZE);
  1827.     procPtr->machStatePtr->userState.trapRegs[SP] = (int)excStackPtr;
  1828.     excStackPtr->statusReg = bufVals[4]&0xf;
  1829.     if (debugProcStubs) {
  1830.     printf("Sigreturn statusReg = %x, pc = %x\n", bufVals[4]&0xf,
  1831.         bufVals[3]);
  1832.     }
  1833.     excStackPtr->vor.stackFormat = MACH_SHORT;
  1834.     excStackPtr->pc = (int)bufVals[3];
  1835.     if (debugProcStubs) {
  1836.     printf("New usp = %x, SP= %x, exSp = %x\n",
  1837.         procPtr->machStatePtr->userState.userStackPtr, 
  1838.         procPtr->machStatePtr->userState.trapRegs[SP],
  1839.         procPtr->machStatePtr->userState.excStackPtr);
  1840.     }
  1841.     return procPtr->machStatePtr->userState.trapRegs[D0];
  1842. }
  1843.